use anyhow::Result;
use std::{fs::File, io::Read};
use ed25519_dalek::{ed25519::signature::SignerMut, Signer, SigningKey, VerifyingKey};

// 这个接口的设计， 可能不是很好。 
trait TextSign{
    fn sign(&self, reader: &mut dyn  Read) ->  Result<Vec<u8>>;
}

trait TextVerify {
    // impl Read      <R: Read>  这种是静态的，   面上面的   &dyn Read 是动态的， 效率上静态肯定会比动态高， 但写业务代码不用纠结这点
    // 关键的是IO 效率

   // fn verify<R: Read>(&self, reader: &mut R, sig: &[u8])  -> Result<bool>;

    fn verify(&self, reader: impl Read, sig: &[u8]) -> Result<bool>;
}

struct Blake3{
    key:[u8; 32],
}

struct Ed25519Singer{
    key:SigningKey,
}

struct Ed25519Verifier{
    key: VerifyingKey,
}

use anyhow::Ok;
use ed25519_dalek::ed25519::signature;

use crate::{cli::text::{TextSignFormat, TextVerifyOpts}, get_reader};

pub fn process_text_sign(input: &str, key: &str, format: TextSignFormat) -> Result<()>{
    let mut reader = get_reader(input)?;
    let mut buf = Vec::new();
    reader.read_to_end(&mut buf)?;

    let signed = match format  {
        TextSignFormat::Blake3 => {
            let key = std::fs::read(key)?;
            let key = &key[..32];
            let key = key.try_into()?;
            let signer = Blake3{ key };
            //let signer = blake3::Hasher::new_keyed(&key);
            signer.sign(&mut reader)?
        },
        TextSignFormat::Ed25519 =>todo!(),  
    };

   //println!("{}",signed);
    Ok(())


}

impl TextSign for Blake3{
    fn sign(&self, reader: &mut dyn Read) ->  Result<Vec<u8>> {
        // TODO: improve performance by reading in chunks
        let mut buf = Vec::new();
        reader.read_to_end(&mut buf)?;
      //  Ok(blake3::hash( &buf).as_bytes().to_vec())
      let signature = blake3::keyed_hash(&self.key, &buf).as_bytes().to_vec();
      Ok(signature)
    }
}

impl TextVerify for Blake3 {
    fn verify(&self, mut reader: impl Read, sig: &[u8]) -> Result<bool> {
        let mut buf = Vec::new();
        reader.read_to_end(&mut buf)?;
        let hash = blake3::hash(&buf);
        let hash = hash.as_bytes();
    
        Ok(hash==sig)
    }
    
}

impl TextSign for Ed25519Singer{
    fn sign(&self, reader: &mut dyn Read) -> Result<Vec<u8>>{
        let mut buf  = Vec::new();
        reader.read_to_end(&mut buf)?;
        let sig = self.key.sign(&buf);
        Ok(sig.to_bytes().to_vec())
    }
}

// impl TextVerify for Ed25519Verifier {
//     fn verify(&self, mut reader:  impl Read, sig: &[u8]) -> Result<bool> {
//          let mut  buf = Vec::new();
//          reader.read_to_end(&mut buf)?;
//          self.key.verify_strict(message, signature);
//          let res = self.key.verify(&buf,&sig);
//          Ok(ret)
//     }
// }



#[cfg(test)]

mod tests{

    #[test]
    fn test_blake3() {
        let hash1 = blake3::hash(b"xugangtwtqmq");
        println!("hash1 :{}",hash1);

        let mut hasher = blake3::Hasher::new();
        hasher.update(b"xugang");
        hasher.update(b"twtqmq");
        let hash2 = hasher.finalize();
        assert_eq!(hash1,hash2);


        let mut output = [0;1000];
        let mut output_reader = hasher.finalize_xof();
        output_reader.fill(&mut output);
        assert_eq!(hash1,output[..32]);

        println!("{}",hash1);

    }

    #[test]
    fn test_256_bit_key(){
        let example_key = [42u8;32];
        let mac1 = blake3::keyed_hash(&example_key, b"xugangtwtqmq");
        println!("mac1 {}", mac1);

        // MAC incrementally.
        let mut hasher = blake3::Hasher::new_keyed(&example_key);
        hasher.update(b"xugangtwtqmq");
        let mac2 = hasher.finalize();
        assert_eq!(mac1,mac2);
    }
 
}

